﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

/// <summary>
/// Base class for a file definition, used to define which data files
/// load what into the database
/// </summary>
public abstract class FileDefinition
{
    Ethnicity eth;
    Field field;
    string desc;

    private FileDefinition() { }

    /// <summary>
    /// Creates a new FileDefinition object.
    /// </summary>
    /// <param name="eth">The ethnicity, or All, that this data represents</param>
    /// <param name="field">The field which this data represents</param>
    /// <param name="desc">The human-readable description of the file</param>
    public FileDefinition(Ethnicity eth, Field field, string desc)
    {
        this.eth = eth;
        this.field = field;
        this.desc = desc;
    }

    /// <summary>
    /// Gets the human-readable description associated with this file
    /// </summary>
    public string Description
    {
        get { return desc; }
    }

    /// <summary>
    /// Gets the ethnicity whose data is contained in this file
    /// </summary>
    public Ethnicity Ethnicity
    {
        get { return eth; }
    }

    /// <summary>
    /// Gets the field whose data is contained in this file
    /// </summary>
    public Field Field
    {
        get { return field; }
    }

    /// <summary>
    /// Parses a line of a CSV file into array fields
    /// </summary>
    /// <param name="line">The CSV data line</param>
    /// <returns>An array of the fields contained inside the data line.</returns>
    protected string[] ParseCSV(string line)
    {
        List<string> fields = new List<string>();

        StringBuilder sbField = new StringBuilder();
        bool inQuote = false;
        for (int i = 0; i <= line.Length; i++)
        {
            // end of field?
            if (i == line.Length || (!inQuote && line[i] == ','))
            {
                // if it's the last character, append it
                fields.Add(sbField.ToString());
                inQuote = false;
                sbField = new StringBuilder();
            }

            // quote at start of field
            else if (line[i] == '"' && !inQuote)
            {
                inQuote = true;
            }

            // quote in quoted-string
            else if (inQuote && line[i] == '"')
            {
                // if it could be a "" escaped quote
                if (i + 1 < line.Length && line[i + 1] == '"')
                {
                    sbField.Append("\"");
                    i++;
                }

                // else if it's just a random quote, end the quoted-string
                else
                    inQuote = false;
            }

            // otherwise just append the character
            else
                sbField.Append(line[i]);
        }

        return fields.ToArray();
    }

    /// <summary>
    /// Called to process the data obtained from the uploaded file
    /// </summary>
    /// <param name="data">A StreamReader object containing the uploaded data</param>
    /// <returns>True if the file is valid, false otherwise</returns>
    public abstract bool ProcessData(StreamReader data);
}